<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>多级菜单-四级</title>
<script src="vue.js"></script>
<style>
*, *::after, *::before {
  box-sizing: border-box;
}

body {
  margin: 0;
}

.container {
  min-height: 100vh;
}

.center {
  display: flex;
  justify-content: center;
  align-items: center;
}

ul {
  list-style: none;
  padding: 0px;
}

.menu {
  width: 100%;
  max-width: 600px;
  margin: auto;
  background: #bbb;
}

.menu label {
  position: relative;
  display: block;
  padding: 18px 18px 18px 45px;
  color: #000;
  cursor: pointer;
}

.menu label::before {
  display: inline-block;
  position: absolute;
  top: 50%;
  left: 18px;
  transform: translateY(-50%);
  font-size: 20px;
  line-height: 1;
  height: 22px;
}

.menu li.item > label::before {
  content: "-";  
}

.menu li.folder > label::before {
  content: ">";
}

.menu label.open::before {
  transform: translateY(-45%) rotate(90deg);
}

.menu ul {
  background: #ddd;
  padding-left: 20px;
}

.slide-enter-active {
  transition-duration: 1s;
}

.slide-leave-active {
  transition-duration: 0.5s;
}

.slide-enter-to, .slide-leave {
  max-height: 500px;
  overflow: hidden;
}

.slide-enter, .slide-leave-to {
  max-height: 0;
  overflow: hidden;
}
.menu label::before {
  transition: transform 0.3s;
}
</style>
</head>
<body>
  <div class="container center" id="app">
    <ul class="menu">
      <menu-item :tree-data="treeData"></menu-item>
    </ul>
  </div>

<script>
Vue.component('menu-item', {
  template: `
  <li v-bind:class="[isFolder ? 'folder' : 'item']">
    <label v-bind:class="{'open': open}" @click="toggle">
      {{treeData.name}}
    </label>
    <transition name="slide">
      <ul v-show="open" v-if="isFolder">
        <!-- 递归调用menu-item组件 -->
        <menu-item 
          v-for="(item, index) in treeData.children"
          :key="index" :treeData="item">
        </menu-item>
      </ul>
    </transition>
  </li>`,
  props: {
    treeData: Object
  },
  data() {
    return { open: false }
  },
  computed: {
    isFolder() {
      return this.treeData.children && this.treeData.children.length > 0;
    }
  },
  methods: {
    toggle() {
      if (this.isFolder) this.open = !this.open;
    }
  }
})

new Vue({
  el: "#app",
  data: {
    treeData: {
      name: "Web开发",
      children: [
        {
          name: "前端开发技术",
          children: [
            { name: "HTML" }, { name: "CSS" },
            { 
              name: "JavaScript",
              children:[{name: 'ES6'}, { name: 'Vue.js'}, { name: 'jQuery'}]
            }]
        },
        {
          name: "后端开发技术",
          children: [{ name: "Node.js" }, { name: "Python" }, { name: "Java" }]
        },
        { name: "工程化技术" }
      ]
    }
  }
});
</script>
</body>
</html>